package org.tlang.ast.list.array;

import org.tlang.ast.AST;
import org.tlang.ast.ASTList;
import org.tlang.context.TypeTable;
import org.tlang.context.ValueTable;
import org.tlang.exception.TypeException;
import org.tlang.type.ArrayType;
import org.tlang.type.Type;
import org.tlang.type.VoidType;

import java.util.List;

/**
 * [1, 2, 1+2]
 */
public class ArrayLiteral extends ASTList {
    public ArrayLiteral(List<AST> children) {
        super(children);
    }

    @Override
    public String toString() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("( [");
        String sep = "";
        for (AST ast : children()) {
            stringBuilder.append(sep);
            sep = ", ";
            stringBuilder.append(ast.toString());
        }
        return stringBuilder.append("] )").toString();
    }

    @Override
    public Type typeCheck(TypeTable typeTable) throws TypeException {
        Type elementType;
        // 将第一个元素的类型作为数组字面量的元素类型
        if (numChildren() > 0) {
            elementType = child(0).typeCheck(typeTable);
        } else {
            return new ArrayType(VoidType.VOID_TYPE, 1);
        }

        // 检查剩下的元素类型是否是第一个类型的子类型
        for (int i = 1; i < numChildren(); i++) {
            if (!child(i).typeCheck(typeTable).isSubTypeOf(elementType, typeTable)) {
                throw new TypeException("bad type of element " + i, child(i));
            }
        }

        if (elementType.isArrayType()) {
            ArrayType arrayType = (ArrayType) elementType;
            return new ArrayType(arrayType.elementType(), arrayType.dimension() + 1);
        } else {
            return new ArrayType(elementType, 1);
        }
    }

    @Override
    public Object eval(ValueTable valueTable) {
        Object[] result = new Object[numChildren()];
        for (int i = 0; i < numChildren(); i++) {
            result[i] = child(i).eval(valueTable);
        }
        return result;
    }
}
